
//A minimal wrapper for a 2-dimensional array.

#ifndef ARRAY2D_H
#define ARRAY2D_H

#include <cassert>

#ifndef NDEBUG
#include <iostream>
#endif

template<typename T, typename uint = std::size_t>
class array2d
{
  protected:
	T** data;
	const uint w;
	const uint h;
	void alloc(const T & fill = T());

  public:
    	typedef T data_type;
    	typedef uint size_type;

	array2d(uint width_, uint height_, const T & fill = T())
		: w(width_), h(height_)
		{ alloc(fill); }

	array2d & operator = (const array2d<T, uint> & other);

	array2d(array2d<T,uint> & other)
		: w(other.width()), h(other.height())
		{ alloc(); this->operator =( other ); }

	array2d(const array2d<T,uint> & other)
		: w(other.width()), h(other.height())
		{ alloc(); this->operator =( other ); }

	~array2d();

	const uint width() const
		{ return w; }

	const uint height() const
		{ return h; }

	T & operator()(uint x, uint y)
		{ return data[x][y]; }

	const T & operator()(uint x, uint y) const
		{ return data[x][y]; }
};

template<typename T, typename uint>
void array2d<T,uint>::alloc(const T & fill)
{
	data = new T*[w];
	for(uint i = 0; i < w; ++i)
	{
		data[i] = new T[h];
		for(uint j = 0; j < h; ++j)
			data[i][j] = fill;
	}
}

template<typename T, typename uint>
array2d<T,uint> & array2d<T,uint>::operator = (const array2d<T,uint> & other)
{
	#ifndef NDEBUG
	std::cout << "!!!!!!!! WARNING array2d BEING COPIED !!!!!!!!" << std::endl;
	#endif
	assert(other.width() == w && other.height() == h);
	for(uint i = 0; i < w; ++i)
	{
		for(uint j = 0; j < h; ++j)
			data[i][j] = other(i,j);
	}
	return *this;
}

template<typename T, typename uint>
array2d<T,uint>::~array2d()
{
   if(data)
   {
	for(uint i = 0; i < w; ++i)
		delete [] data[i];
	delete [] data;
	data = 0;
   }
}

template<typename T, typename uint, class ternary_func_t>
inline void special_for_each(array2d<T,uint> & a, ternary_func_t & f)
{
	for(uint i = 0; i < a.width(); ++i)
	{
		for(uint j = 0; j < a.height(); ++j)
			f( i, j, a );   //notice the order of the arguments
	}
}

template<typename T, typename uint, class unary_func_t>
inline void for_each(array2d<T,uint> & a, unary_func_t & f)
{
	for(uint i = 0; i < a.width(); ++i)
	{
		for(uint j = 0; j < a.height(); ++j)
			f( a(i,j) );   //notice the order of the arguments
	}
}

#endif

